//
//  SubModule.swift
//  JKTool
//
//  Created by 姜奎 on 2022/6/22.
//

import Foundation
import PathKit

extension JKTool.Git {
    
    struct SubModule: ParsableCommand {
        static var configuration = CommandConfiguration(
            commandName: "submodule",
            _superCommandName: "git",
            abstract: "利用git submodule构建/更新项目结构",
            version: "1.0.0")
        
        @Option(name: .shortAndLong, help: "强制 checkout，default：false")
        var force: Bool = false
        
        @Option(name: .long, help: "移除不在SubModule中的SubProject，default：false")
        var prune: Bool?
        
        @Option(name: .shortAndLong, help: "是否自动利用git submodule构建/更新项目结构，default：true")
        var autoAddSubmodule: Bool = true
        
        @Option(name: .shortAndLong, help: "更新 submodule 为远程项目的最新版本，default：false")
        var remote: Bool?
        
        @Option(name: .shortAndLong, help: "分支名")
        var branch: String?

        @Option(name: .shortAndLong, help: "兜底分支")
        var currentBranch: String?

        @Option(name: .shortAndLong, help: "遇到错误时终止，default：false")
        var exitError: Bool = false
        
        @Option(name: .shortAndLong, help: "执行目录")
        var path: String?
        
        mutating func run() {
            
            
            guard let project = Project.project(directoryPath: path ?? FileManager.default.currentDirectoryPath) else {
                return po(tip: "\(path ?? FileManager.default.currentDirectoryPath)目录没有检索到工程", type: .error)
            }
            
            guard project.rootProject == project else {
               return po(tip: "请在项目根目录执行脚本", type: .error)
            }
            
            po(tip: "======Update子模块开始======", type: .tip)
            let date = Date.init().timeIntervalSince1970
            let gitSubmodules = project.gitSubmodules
            
            var cloneHistory: [String] = []
            
            func submodule(project:Project) -> [String] {
                
                var subRecordList:[String] = []
                for module in project.moduleList {
                    
                    // 组装module路径
                    let modulePath = project.rootProject.checkoutsPath + "/" + module.name
                    
                    func gitSubmoduleUpdate() {
                        po(tip: "【\(module.name)】开始执行：git submodule update")
                        do {
                            try shellOut(to: .gitSubmoduleUpdate(remote: remote ?? false,path: "\(ModulesConfigs.sharedInstance.config.checkouts)/\(module.name)", force: force),at: project.rootProject.directoryPath)
                            po(tip: "【\(module.name)】update 成功")
                        } catch {
                            let error = error as! ShellOutError
                            po(tip:"【\(module.name)】update 异常" + error.message + error.output,type: .exitError(exitError))
                        }
                    }
                    
                    func gitSubModuleAdd() {
                        do {
                            po(tip: "【\(module.name)】开始执行：git submodule add")
                            try shellOut(to: .gitSubmoduleAdd(name: module.name,url: module.url, path: "\(ModulesConfigs.sharedInstance.config.checkouts)/\(module.name)",branch: module.branch),at: project.rootProject.directoryPath)
                            po(tip: "【\(module.name)】Add 成功")
                        } catch {
                            let error = error as! ShellOutError
                            po(tip: "【\(module.name)】Add 异常" + error.message + error.output,type: .error)
                        }
                    }
                    
                    func gitClone() {
                        do {
                            po(tip: "【\(module.name)】开始执行：git clone")
                            let date = Date.init().timeIntervalSince1970
                            try shellOut(to: .gitClone(url: module.url, to: modulePath, branch: module.branch))
                            po(tip: "【\(module.name)】clone成功[\(GlobalConstants.duration(to: date) + " s")]")
                        } catch {
                            let error = error as! ShellOutError
                            po(tip: "【\(module.name)】clone失败：\n" + error.message + error.output,type: .error)
                        }
                    }
                    
                    func gitCheckout() {
                        JKTool.Git.Checkout.main(["--path",modulePath,"--branch",(branch ?? module.branch ?? "master"), "--current-branch",(currentBranch ?? module.branch ?? "master"), "--force",String(force),"--exit-error",String(exitError)])
                    }
                
                    if !cloneHistory.contains(module.name) {
                        if FileManager.default.fileExists(atPath: modulePath),
                           FileManager.default.getFileList(directoryPath: modulePath)?.isEmpty == false {
                            po(tip: "【\(module.name)】已经存在！",type: .warning)
                            if remote == true {
                                if gitSubmodules.contains(module.name) {
                                    gitSubmoduleUpdate()
                                } else {
                                    gitCheckout()
                                }
                            }
                        } else if autoAddSubmodule == true {
                            gitSubModuleAdd()
                            gitCheckout()
                        } else {
                            po(tip: "【\(module.name)】是否加入git submodule(y/n):")
                            if let tool = readLine(), tool.lowercased().hasPrefix("y") {
                                gitSubModuleAdd()
                                gitCheckout()
                            } else {
                                gitClone()
                                gitCheckout()
                            }
                        }
                            //创建module的Project
                        if let subModule = Project.project(directoryPath: modulePath) {
                                // 递归Clone subModule
                            let list = submodule(project: subModule)

                            do {
                                _ = try subModule.writeRecordList(recordList: list)
                                po(tip: "【\(subModule.directoryEntrance)】Modulefile.recordList 写入成功")
                            } catch {
                                po(tip: "【\(subModule.directoryEntrance)】Modulefile.recordList 写入失败",type: .error)
                            }

                            subRecordList += list
                                // 将module加入即将需要subModule中
                            subRecordList.append(module.name)
                        }else{
                            po(tip: "【\(module.name)】初始化失败，请检查项目",type: .error)
                        }

                        cloneHistory.append(module.name)
                    } else {
                            //创建module的Project
                        if let subModule = Project.project(directoryPath: modulePath) {
                                // 递归Clone subModule
                            let list = submodule(project: subModule)

                            subRecordList += list
                                // 将module加入即将需要subModule中
                            subRecordList.append(module.name)
                        }else{
                            po(tip: "【\(module.name)】初始化失败，请检查项目",type: .error)
                        }
                    }
                }
                
                return subRecordList.filterDuplicates()
            }
            
            let subRecordList = submodule(project: project)
            
            guard let pruneRecordList = try? project.writeRecordList(recordList: subRecordList) else {
                po(tip: "【\(project.directoryEntrance)】Modulefile.recordList 写入失败",type: .error)
                return
            }

            if prune == true {
                for record in pruneRecordList {
                    if gitSubmodules.contains(record) {
                        do {
                            try shellOut(to: .gitSubmoduleRemove(path: "\(ModulesConfigs.sharedInstance.config.checkouts)/\(record)"),at: project.rootProject.directoryPath)
                            po(tip: "【\(record)】Remove 成功")
                        } catch {
                            let error = error as! ShellOutError
                            po(tip: "【\(record)】Remove 异常" + error.message + error.output,type: .exitError(exitError))
                        }
                    } else {
                        do {
                            try shellOut(to: .removeFolder(from: "\(project.rootProject.checkoutsPath)/\(record)"),at: project.rootProject.directoryPath)
                            po(tip: "【\(record)】Remove 成功")
                        } catch {
                            let error = error as! ShellOutError
                            po(tip: "【\(record)】Remove 异常" + error.message + error.output,type: .exitError(exitError))
                        }
                    }
                }
            }
            po(tip: "======Update子模块完成[\(GlobalConstants.duration(to: date) + " s")]======")
        }
    }
}


